package top.xuziyi.crawler.job;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import top.xuziyi.common.pojo.*;
import top.xuziyi.crawler.service.StockCwzbService;
import top.xuziyi.crawler.service.StockLbService;
import top.xuziyi.crawler.service.StockService;
import top.xuziyi.crawler.service.StockZsService;
import top.xuziyi.crawler.util.ApiUtils;
import top.xuziyi.crawler.util.StockUtils;

import java.util.ArrayList;
import java.util.List;

import static top.xuziyi.crawler.util.StockUtils.MAPPER;

//@Component
public class StockAllJob {

    private static Logger logger = LogManager.getLogger(StockAllJob.class.getName());

    @Autowired
    private ApiUtils apiUtils;
    @Autowired
    private StockLbService stockLbService;
    @Autowired
    private StockZsService stockZsService;
    @Autowired
    private StockService stockService;
    @Autowired
    private StockCwzbService stockCwzbService;

    // status状态,1是初始化完成,2获取完交易数据,4是获取完除权数据
    private List<StockLb> stockLbList;
    private List<StockZs> stockZsList;

    //同步锁
    //private static final String key = "key";

    //initial-delay是任务第一次被调用前的延时，单位毫秒
    //fixed-delay是上一个调用完成后再次调用的延时
    //fixed-rate是上一个调用开始后再次调用的延时（不用等待上一次调用完成）
    //cron是表达式，表示在什么时候进行任务调度
    //初始查询任务
    @Scheduled(cron = "${initStockAll}")
    //@Scheduled(initialDelay = 1000l, fixedDelay = 86400000l)
    public void initStock() {
        //synchronized (key) {
        try {
            //获取股票数据
            stockLbList = stockLbService.findAll();
            //获取股指数据
            stockZsList = stockZsService.findAll();
        } catch (Exception e) {
            logger.error("数据库查询股票和股票指数失败!,初始化交易数据任务列表失败");
            e.printStackTrace();
        }
        logger.info("任务列表初始化完成");
        //}
    }

    //获取股票交易数据
    @Scheduled(cron = "${getStockAll}")
    //@Scheduled(initialDelay = 3000l, fixedDelay = 3000l)
    public void getStock() {
        int count = 0;
        try {
            count = init(count);

            for (StockLb lb : stockLbList) {
                //股票金融数据
                saveCwzb(lb.getSymbol());
                logger.info(lb.getSymbol()+"个股金融数据单独第一次抓取");
            }
        } catch (Exception e) {
            logger.error("单独抓金融数据出错");
            e.printStackTrace();
        }

        //synchronized (key) {

        logger.info("开始抓取数据");
        for (StockLb stockLb : stockLbList) {
            try {
                //判断数据是否已经抓取成功
                if ("e".equals(stockLb.getStatus())) {
                    continue;
                }

                //解决雪球反爬虫的问题
                count = init(count);

                for (StockLb lb : stockLbList) {
                    //股票金融数据
                    saveCwzb(lb.getSymbol());
                }

                //period 日线:day  周线:week  月线:month
                //type 不复权:normal  前复权:before  后复权:after
                //股票,抓取不复权数据
                saveStock(stockLb.getSymbol(), "day", "normal");
                //股票,抓取后复权数据
                saveStock(stockLb.getSymbol(), "day", "after");
                //股票,周线
                saveStock(stockLb.getSymbol(), "week", "normal");
                //股票,月线
                saveStock(stockLb.getSymbol(), "month", "normal");

                //股票金融数据
                saveCwzb(stockLb.getSymbol());

                logger.info(stockLb.getSymbol() + "个股抓取完成");

                stockLbService.updateStatus(stockLb.getSymbol(), "e");
                stockLb.setStatus("e");
            } catch (Exception e) {
                logger.error(stockLb.getSymbol() + "个股抓取失败");
                e.printStackTrace();
            }
        }

        for (StockZs stockZs : stockZsList) {
            try {
                //判断数据是否已经抓取成功
                if ("e".equals(stockZs.getStatus())) {
                    continue;
                }

                //解决雪球反爬虫的问题
                count = init(count);

                //指数,日线
                saveStock(stockZs.getSymbol(), "day", "normal");
                //指数,周线
                saveStock(stockZs.getSymbol(), "week", "normal");
                //指数,月线
                saveStock(stockZs.getSymbol(), "month", "normal");

                stockZsService.updateStatus(stockZs.getSymbol(), "e");
                stockZs.setStatus("e");
                logger.info(stockZs.getSymbol() + "指数抓取完成");
            } catch (Exception e) {
                logger.error(stockZs.getSymbol() + "指数抓取失败");
                e.printStackTrace();
            }
        }
        logger.info("结束抓取数据");
        //}
    }

    //period日周月线  type复权
    private void saveStock(String symbol, String period, String type) throws Exception {
        DateTime date = DateTime.now();
        while (true) {
            String url = "https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=" + symbol + "&begin=" +
                    date.toDate().getTime() + "&period=" + period + "&type=" + type + "&count=-800&indicator=kline";

            String content = apiUtils.getHtmlUTF8Check(url);

            ArrayNode arrayNode = (ArrayNode) MAPPER.readTree(content).get("data").get("item");

            if (arrayNode.size() == 0) {
                return;
            }

            //type 不复权:normal  前复权:before  后复权:after
            if ("day".equals(period)) {
                if ("normal".equals(type)) {
                    //获取不复权日线
                    List<StockDayNormal> list = new ArrayList<>();
                    for (JsonNode jsonNode : arrayNode) {
                        StockDayNormal stockDayNormal = StockUtils.getStockDayNormal(jsonNode);
                        if (stockDayNormal != null) {
                            stockDayNormal.setSymbol(symbol);
                            list.add(stockDayNormal);
                        }
                    }
                    stockService.batchSaveStockDayNormal(list);
                } else {
                    //获取后复权日线
                    List<StockDayAfter> list = new ArrayList<>();
                    for (JsonNode jsonNode : arrayNode) {
                        StockDayAfter stockDayAfter = StockUtils.getStockDayAfter(jsonNode);
                        if (stockDayAfter != null) {
                            stockDayAfter.setSymbol(symbol);
                            list.add(stockDayAfter);
                        }
                    }
                    stockService.batchSaveStockDayAfter(list);
                }
                //日线日期减2年
                date = date.minusYears(2);

            } else if ("week".equals(period)) {
                List<StockWeek> list = new ArrayList<>();
                for (JsonNode jsonNode : arrayNode) {
                    StockWeek stockWeek = StockUtils.getStockWeek(jsonNode);
                    if (stockWeek != null) {
                        stockWeek.setSymbol(symbol);
                        list.add(stockWeek);
                    }
                }
                stockService.batchSaveStockWeek(list);
                //周线日期减10年
                date = date.minusYears(10);
            } else if ("month".equals(period)) {
                List<StockMonth> list = new ArrayList<>();
                for (JsonNode jsonNode : arrayNode) {
                    StockMonth stockMonth = StockUtils.getStockMonth(jsonNode);
                    if (stockMonth != null) {
                        stockMonth.setSymbol(symbol);
                        list.add(stockMonth);
                    }
                }
                stockService.batchSaveStockMonth(list);
                //月线日期减40年
                date = date.minusYears(40);
            }
        }
    }

    private void saveCwzb(String symbol) throws Exception {
        //String url = "http://vip.stock.finance.sina.com.cn/corp/go" +
        //        ".php/vFD_FinancialGuideLine/stockid/601628/displaytype/4.phtml";

        for (int year = 2018; year > 1999; year--) {
            String url = "http://money.finance.sina.com.cn/corp/go.php/vFD_FinancialGuideLine/stockid/" +
                    symbol.substring(2) + "/ctrl/" + year + "/displaytype/4.phtml";

            String content = apiUtils.getHtmlGb2312Check(url);

            List<StockCwzb> stockCwzbList = StockUtils.getCwzb(content, symbol);

            if (stockCwzbList == null) {
                break;
            }
            stockCwzbService.batchSave(stockCwzbList);
        }
    }

    //@Scheduled(cron = "0 0 * * * ?")
    private int init(int count) {
        count++;
        if (count % 50 != 1) {
            return count;
        }


        try {
            //需求设置cookie,解决反爬虫问题
            String indexUrl = "https://xueqiu.com";

            CookieStore cookieStore = new BasicCookieStore();
            CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();

            HttpGet httpGet = new HttpGet(indexUrl);
            httpClient.execute(httpGet);

            ApiUtils.cookieStore = cookieStore;

        } catch (Exception e) {
            logger.error("访问雪球首页出错");
        }
        return count;
    }

}
